package com.runner.player.state;

import com.runner.entity.CollisionEntity;
import com.runner.observer.Event;
import com.runner.player.Player;

public class JumpState extends PlayerState {

	private boolean hitGround;
	private boolean peaked;
	private boolean requestRoll;
	private float jumpTimer;

	public JumpState(Player p) {
		super(p);
	}

	@Override
	public void update(float delta) {
		if (hitGround) {
			// if the player hit the roll button, roll immediately after hitting
			// the ground
			if (!requestRoll) {
				player.changeState(new NormalState(player));
			} else {
				player.changeState(new RollState(player));
			}
			exit();
		}
		if (!peaked) {
			// allow player to float a little more if they hold jump button
			// after hitting highest point
			if (player.getPhysics().getBody().getLinearVelocity().y < 0) {
				player.getPhysics().getBody().setGravityScale(Player.JUMP_GRAVITY_PEAKED_SCALE);
				peaked = true;
				//start floating if april is jumping
				if(player.getPlayerType().equals(PLAYER_TYPE.APRIL)){
					exit();
					player.changeState(new FloatState(player));
				}
			}
		}
		jumpTimer+=delta;
		if(!peaked && jumpTimer < player.getJumpTimer()){
			player.getPhysics().getBody().setLinearVelocity(player.getJumpVelocity().scl(delta));
		}
	}

	@Override
	public void newAction(INPUT input) {
		switch (input) {
		case TOUCH_UP:
			player.getPhysics().getBody().setGravityScale(2);
			//if user stops holding up, immediately drop the velocity
			if (!peaked) {
				//player.getPhysics().getBody().setLinearVelocity(0,0);
				peaked = true;
			}
			break;
		case JUMP:
			// only april cant double jump
			if (!player.getPlayerType().equals(PLAYER_TYPE.APRIL)) {
				exit();
				player.changeState(new DoubleJumpState(player));
			} else if(player.getPlayerType().equals(PLAYER_TYPE.APRIL)){
				exit();
				player.getPhysics().getBody().setLinearVelocity(0,0);
				player.changeState(new FloatState(player));
			}
			break;
		case ROLL:
			if (peaked) {
				requestRoll = true;
			}
			break;
		case DIVE:
			exit();
			player.changeState(new AirDiveState(player));
			break;
		default:
			break;

		}
	}

	@Override
	public void enter() {
		jumpTimer=0;
		peaked = false;
		requestRoll = false;
		hitGround = false;
		player.getSubject().notify(Event.EVENT_JUMP);
		player.getPhysics().getBody().setGravityScale(player.getJumpGravityScale());
	}

	@Override
	public void exit() {
		player.getPhysics().getBody().setGravityScale(1);
	}

	@Override
	public void collide(CollisionEntity otherBody) {
		if (jumpTimer > 0.05f && otherBody.getPhysics().getType().equals(TYPE.GROUND)) {
			hitGround = true;
			player.getSubject().notify(Event.EVENT_PLAYER_HIT_GROUND);
		}

	}

}
